package com.sdleyou.treepro.common.service.impl;

import com.sdleyou.treepro.common.exception.ServiceException;
import com.sdleyou.treepro.common.model.convert.CompanyDO2CompanyVOConverter;
import com.sdleyou.treepro.common.model.convert.UCADO2UCAVO;
import com.sdleyou.treepro.common.model.convert.UserDO2CompanyUserVO;
import com.sdleyou.treepro.common.model.dao.*;
import com.sdleyou.treepro.common.model.dto.CompanyDTO;
import com.sdleyou.treepro.common.model.enums.CompanyStatusEnum;
import com.sdleyou.treepro.common.model.enums.ErrorCodeEnum;
import com.sdleyou.treepro.common.model.utils.RandomUtil;
import com.sdleyou.treepro.common.model.vo.CompanyUserVO;
import com.sdleyou.treepro.common.model.vo.CompanyVO;
import com.sdleyou.treepro.common.model.vo.CurrentUserVO;
import com.sdleyou.treepro.common.model.vo.UserCompanyAppliesVO;
import com.sdleyou.treepro.common.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserCompanyManagerImpl implements UserCompanyManager {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoPageManager mongoPageManager;
    @Autowired
    private CompanyManager companyManager;
    @Autowired
    private UserManager userManager;

    @Override
    public void initCompany(CompanyDTO companyDTO) {
        Query query = new Query(Criteria.where("company_name").is(companyDTO.getCompanyName()));
        CompanyDO companyDO = mongoTemplate.findOne(query, CompanyDO.class);
        if (companyDO != null) {
            throw new ServiceException(ErrorCodeEnum.E008.code(), "公司名称已存在");
        }
        query = new Query(Criteria.where("leader_id").is(companyDTO.getLeaderId()).and("company_status").is(CompanyStatusEnum.APPLY.name()));
        companyDO = mongoTemplate.findOne(query, CompanyDO.class);
        if (companyDO != null) {
            throw new ServiceException(ErrorCodeEnum.E009.code(), "您的公司正在审核中");
        }
        query = new Query(Criteria.where("leader_id").is(companyDTO.getLeaderId()).and("company_status").is(CompanyStatusEnum.OPEN.name()));
        companyDO = mongoTemplate.findOne(query, CompanyDO.class);
        if (companyDO != null) {
            throw new ServiceException(ErrorCodeEnum.E010.code(), "您已经申请过公司了");
        }
        CompanyDO newCompany = new CompanyDO();
        newCompany.setCompanyId(RandomUtil.randomId());
        newCompany.setCompanyName(companyDTO.getCompanyName());
        newCompany.setCompanyIcon(companyDTO.getCompanyIcon());
        newCompany.setLeaderId(companyDTO.getLeaderId());
        newCompany.setLeaderName(companyDTO.getLeaderName());
        newCompany.setInformation(companyDTO.getInformation());
        newCompany.setCompanyStatus(CompanyStatusEnum.APPLY.name());
        newCompany.setMemberCount(1);
        newCompany.setTreeCount(0);
        Date date = new Date();
        newCompany.setGmtCreate(date.getTime());
        newCompany.setGmtModified(date.getTime());
        newCompany.setApplyAt(date.getTime());
        mongoTemplate.insert(newCompany);
        return;
    }

    @Override
    public Page<CompanyUserVO> companyUsers(String companyId, String userId, Integer pageSize, Integer pageNum, String keywords) {
        Query query = new Query();
        Criteria c = Criteria.where("company_id").is(companyId);
        //用户名搜索
        if (!StringUtils.isEmpty(keywords)) {
            c.and("nickname").regex(".*?" + keywords + ".*");
        }
        //根据公司贡献值倒序排列
        Sort sort = Sort.by(Sort.Direction.DESC, "company_contribute");
        query.addCriteria(c).with(sort);
        Page<UserDO> page = mongoPageManager.pageQuery(query, UserDO.class, pageSize, pageNum);
        List<UserDO> userDOList = page.getData();
        List<CompanyUserVO> companyUserVOList = userDOList.stream()
                .map(e -> UserDO2CompanyUserVO.convert(e))
                .collect(Collectors.toList());

        return new Page<>(page.getPageNo(), page.getDataTotal(),
                page.getPageSize(), this.canMakeFriends(companyUserVOList, userId));
    }

    /**
     * 判断能否添加好友
     *
     * @param companyUserVO
     * @param userId
     * @return
     */
    private List<CompanyUserVO> canMakeFriends(List<CompanyUserVO> companyUserVO, String userId) {
        if (companyUserVO != null && companyUserVO.size() > 0) {
            for (int i = 0; i < companyUserVO.size(); i++) {
                if (!companyUserVO.get(i).getUserId().equals(userId)) { //不是自己
                    Query query = new Query(Criteria.where("user_id").is(userId).and("friend_id").is(companyUserVO.get(i).getUserId()));
                    FriendDO friendDO = mongoTemplate.findOne(query, FriendDO.class);
                    if (friendDO != null) {
                        companyUserVO.get(i).setMakeFriends(false); //已经加过了
                    } else {
                        companyUserVO.get(i).setMakeFriends(true); //可以加
                    }
                } else {
                    companyUserVO.get(i).setMakeFriends(false); //是自己 不能加
                }
            }
        }
        return companyUserVO;
    }

    /**
     * 获取公司信息
     *
     * @param companyId
     * @return
     */
    @Override
    public CompanyVO getCompany(String companyId, String userId) {
        Query query = new Query(Criteria.where("company_id").is(companyId));
        CompanyDO companyDO = mongoTemplate.findOne(query, CompanyDO.class);
        if (companyDO == null) {
            throw new ServiceException(ErrorCodeEnum.E013.code(), ErrorCodeEnum.E013.name());
        }
        Query queryUser = new Query(Criteria.where("user_id").is(userId).and("company_id").is(companyId));
        UserDO userDO = mongoTemplate.findOne(queryUser, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.name());
        }
        Query queryMyRank = new Query(Criteria.where("company_id").is(companyId).and("user_id").ne(userId).and("company_contribute").gt(userDO.getCompanyContribute()));
        Long myRank = mongoTemplate.count(queryMyRank, UserDO.class);
        CurrentUserVO currentUserVO = new CurrentUserVO();
        currentUserVO.setUserId(userDO.getUserId());
        currentUserVO.setUserName(userDO.getNickname());
        currentUserVO.setFace(userDO.getFace());
        currentUserVO.setContribute(userDO.getCompanyContribute());
        currentUserVO.setRank(myRank + 1);
        currentUserVO.setRole(userDO.getRole());
        //公司排名
        CompanyVO companyVO = new CompanyVO();
        BeanUtils.copyProperties(companyDO, companyVO);
        Query rankQuery = new Query(Criteria.where("company_id").ne(companyId).and("tree_count").gt(companyDO.getTreeCount()));
        Long rank = mongoTemplate.count(rankQuery, CompanyDO.class);
        companyVO.setRank(rank + 1);//设置公司排名
        companyVO.setCurrentUser(currentUserVO);
        //当前申请总数
        Query queryApply = new Query(Criteria.where("company_id").is(companyId).and("status").is("APPLY"));
        long totalApply = mongoTemplate.count(queryApply, UserCompanyApplyDO.class);
        companyVO.setTotalApply(new Integer((int) totalApply));
        return companyVO;
    }

    @Override
    public Page<CompanyVO> getCompanies(Integer pageSize, Integer pageNum, String keywords) {
        Query query = new Query();
        Criteria c = Criteria.where("company_status").is("OPEN");
        if (!StringUtils.isEmpty(keywords)) {
            c.and("company_name").regex(".*?" + keywords + ".*");
        }
        Sort sort = Sort.by(Sort.Direction.DESC, "tree_count");
        query.addCriteria(c).with(sort);
        Page<CompanyDO> page = mongoPageManager.pageQuery(query, CompanyDO.class, pageSize, pageNum);
        List<CompanyDO> companyDOList = page.getData();
        List<CompanyVO> companyVOList = companyDOList.stream().map(e -> CompanyDO2CompanyVOConverter.convert(e)).collect(Collectors.toList());

        return new Page<>(page.getPageNo(), page.getDataTotal(), page.getPageSize(), companyVOList);
    }

    @Override
    public void quitCompany(String companyId, String userId) {
        Query queryUser = new Query(Criteria.where("user_id").is(userId).and("company_id").is(companyId));
        UserDO userDO = mongoTemplate.findOne(queryUser, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        Update updateUser = new Update();
        updateUser.set("company_id", "");
        updateUser.set("company_contribute", 0);
        mongoTemplate.updateFirst(queryUser, updateUser, UserDO.class);
        Query queryCompany = new Query(Criteria.where("company_id").is(companyId));
        CompanyDO companyDO = mongoTemplate.findOne(queryCompany, CompanyDO.class);
        Update updateCompany = new Update();
        int memberCount = (companyDO.getMemberCount() - 1) < 0 ? 0 : companyDO.getMemberCount() - 1;
        updateCompany.set("member_count", memberCount);
        mongoTemplate.updateFirst(queryCompany, updateCompany, CompanyDO.class);
        return;
    }

    @Override
    public void joinCompany(String companyId, String userId) {
        Query queryUser = new Query(Criteria.where("user_id").is(userId));
        UserDO userDO = mongoTemplate.findOne(queryUser, UserDO.class);
        if (userDO == null) {
            throw new ServiceException(ErrorCodeEnum.E100.code(), ErrorCodeEnum.E100.getDescription());
        }
        Query queryCompany = new Query(Criteria.where("company_id").is(companyId));
        CompanyDO companyDO = mongoTemplate.findOne(queryCompany, CompanyDO.class);
        if (companyDO == null) {
            throw new ServiceException(ErrorCodeEnum.E013.code(), ErrorCodeEnum.E013.getDescription());
        }
        if (!StringUtils.isEmpty(userDO.getCompanyId())) {
            throw new ServiceException(ErrorCodeEnum.E016.code(), ErrorCodeEnum.E016.getDescription());
        }
        Query queryApply = new Query(Criteria.where("user_id").is(userId).and("status").is("APPLY"));
        UserCompanyApplyDO applyDO = mongoTemplate.findOne(queryApply, UserCompanyApplyDO.class);
        if (applyDO != null) {
            throw new ServiceException(ErrorCodeEnum.E017.code(), ErrorCodeEnum.E017.getDescription());
        }
        UserCompanyApplyDO newApply = new UserCompanyApplyDO();
        newApply.setCompanyId(companyId);
        newApply.setUserId(userDO.getUserId());
        newApply.setUserName(userDO.getNickname());
        newApply.setFace(userDO.getFace());
        newApply.setStatus("APPLY");
        Date date = new Date();
        newApply.setGmtCreate(date.getTime());
        newApply.setGmtModified(date.getTime());
        mongoTemplate.insert(newApply);
        return;
    }

    @Override
    public Page<UserCompanyAppliesVO> companyApplies(String companyID, String status, Integer pageSize, Integer pageNum) {
        Query query = new Query();
        Criteria c = Criteria.where("company_id").is(companyID).and("status").is(status);
        Sort sort = Sort.by(Sort.Direction.DESC, "gmt_create");
        query.addCriteria(c).with(sort);
        Page<UserCompanyApplyDO> page = mongoPageManager.pageQuery(query, UserCompanyApplyDO.class, pageSize, pageNum);
        List<UserCompanyApplyDO> applyDOList = page.getData();
        List<UserCompanyAppliesVO> appliesVOList = applyDOList.stream().map(e -> UCADO2UCAVO.convert(e)).collect(Collectors.toList());
        return new Page<>(page.getPageNo(), page.getDataTotal(), page.getPageSize(), appliesVOList);
    }

    @Override
    public void auditApply(String companyId, String userId, String status) {
        Query query = new Query(Criteria.where("company_id").is(companyId).and("user_id").is(userId).and("status").is("APPLY"));
        UserCompanyApplyDO applyDO = mongoTemplate.findOne(query, UserCompanyApplyDO.class);
        if (applyDO == null) {
            throw new ServiceException(ErrorCodeEnum.E018.code(), ErrorCodeEnum.E018.getDescription());
        }
        Date date = new Date();
        Update update = new Update();
        update.set("status", status);
        update.set("gmt_modified", date.getTime());
        if (status.equals("PASS")) {
            update.set("gmt_pass", date.getTime());
            companyManager.additionStaff(companyId);
            userManager.joinCompany(userId, companyId);
        }
        mongoTemplate.updateFirst(query, update, UserCompanyApplyDO.class);
        return;
    }
}
